package com.iwhalecloud.bss.kite.cucc.service.pos.handler.impl;

import com.google.common.collect.Lists;
import com.iwhalecloud.bss.kite.client.api.scene.query.IQuerySceneAccessProdInstService;
import com.iwhalecloud.bss.kite.client.dto.cust.ContextCustDTO;
import com.iwhalecloud.bss.kite.client.dto.inst.InstAttrDTO;
import com.iwhalecloud.bss.kite.client.dto.inst.ProdInstDTO;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteDateUtils;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteMapUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.client.dto.cust.CuccContextCustDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosAttrDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosGoodsDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosUserDTO;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalKeyConsts;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalServiceOfferConsts;
import com.iwhalecloud.bss.kite.cucc.service.attr.LocalQuerySeqHelper;
import com.iwhalecloud.bss.kite.cucc.service.pos.handler.CuccPosServiceUtils;
import com.iwhalecloud.bss.kite.cucc.service.pos.handler.KitePosHandlerContext;
import com.iwhalecloud.bss.kite.cucc.service.util.ChangeTypeUtils;
import com.iwhalecloud.bss.kite.cucc.service.util.KiteDcPublicUtils;
import com.iwhalecloud.bss.kite.cucc.spec.impl.transfer.GoodsInfoTransfer;
import com.iwhalecloud.bss.kite.dataservice.cache.DcPublicCache;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferCache;
import com.iwhalecloud.bss.kite.dataservice.cache.ProductCache;
import com.iwhalecloud.bss.kite.dataservice.entity.DcPublic;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.inst.KiteAttr;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteSceneInst;
import com.ztesoft.bss.common.bo.UserInfo;
import com.ztesoft.bss.common.util.ContextUtil;
import com.ztesoft.bss.common.util.SpringUtil;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

public abstract class KitePosBaseUserHandler {
    @Autowired
    protected IQuerySceneInstService querySceneInstService;

    @Autowired
    private IQuerySceneAccessProdInstService querySceneProdInstService;

    protected String getUserId(String sceneInstId, String offerInstId, InstType offerInstType, CuccContextCustDTO custDTO) {
        List<KiteProdInst> prodInsts = this.querySceneInstService
            .listProdInstsFromOfferInst(custDTO.getCustId(), offerInstId).stream()
            .filter(prodInst -> (!LocalKeyConsts.PROD_USE_TYPE_2000.equals(ProductCache.get(prodInst.getSpecId()).getProdUseType()) && !KiteStringUtils.isEmpty(prodInst.getAttrValue("userInstId"))))
            .collect(Collectors.toList());

        if (!KiteListUtils.isEmpty(prodInsts)) {
            return prodInsts.get(0).getAttrValue("userInstId");
        }
        Map<String, String> inParam = new HashMap<>();
        inParam.put("SEQ_TYPE", "USER_ID");
        inParam.put("SYS_TYPE", "1");
        inParam.put("SYS_SOURCE", "");
        String userId = LocalQuerySeqHelper.getSeqBySeqType(inParam, sceneInstId, custDTO);
        return userId;
    }

    protected String getSerialNumber(KitePosHandlerContext context) {
        IQuerySceneInstService querySceneInstService = (IQuerySceneInstService) SpringUtil
            .getBean(IQuerySceneInstService.class);
        String serialNumber = querySceneInstService.getCommonAttrValue(context.getSceneInstId(), "business_number");
        if (KiteStringUtils.isEqual(LocalKeyConsts.EMPTY_SERIAL_NUMBER, serialNumber)) {
            Map<String, String> inParam = new HashMap<>();
            ContextCustDTO custDTO1 = context.getCustDto();
            CuccContextCustDTO custDTO = KiteBeanUtils.transform(custDTO1, CuccContextCustDTO.class);
            inParam.put("SEQ_TYPE", "SERIAL_NUMBER");
            inParam.put("SYS_TYPE", "1");
            inParam.put("SYS_SOURCE", "");
            serialNumber = LocalQuerySeqHelper.getSeqBySeqType(inParam, context.getSceneInstId(), custDTO);
        }
        return serialNumber;
    }

    protected KitePosUserDTO packagePosUser(KitePosHandlerContext context, KiteSceneInst kiteSceneInst,
                                          String createDateStr, String bizType) {
        KitePosUserDTO user = new KitePosUserDTO();
        user.setName(querySceneInstService.getCommonAttrValue(context.getSceneInstId(), "group_user_name"));

        // 0511 改造计费周期、付费类型、计费类型、缴费周期、账务周期放在user节点传给订单中心
        user.setChargeCycle(querySceneInstService.getCommonAttrValue(context.getSceneInstId(), "ORD10235"));
        user.setPayMode(querySceneInstService.getCommonAttrValue(context.getSceneInstId(), "ORD10236"));
        user.setBillType(querySceneInstService.getCommonAttrValue(context.getSceneInstId(), "ORD10240"));
        user.setFeeCycle(querySceneInstService.getCommonAttrValue(context.getSceneInstId(), "ORD10233"));
        user.setAccountCycle(querySceneInstService.getCommonAttrValue(context.getSceneInstId(), "ORD10234"));
        List<KitePosAttrDTO> attrList = new ArrayList<>();

        String renderOrderType = querySceneInstService.getExtParameterValue(context.getSceneInstId(), "renderOrderType");
        if(KiteStringUtils.isEqual(renderOrderType, "orderFallPlace")) {
            // 落地方/收费方产品补录情况，用户关系节点新增两个字段

            KiteOfferInst offerInst = querySceneInstService.getOfferInst(kiteSceneInst.getCustId(), kiteSceneInst.getRootInstId());
            String offerId = Optional.ofNullable(offerInst).map(KiteOfferInst::getOfferId).orElse(null);
            List<DcPublic> list = DcPublicCache.get("20210719001");
            // 产品类型：1：落地方产品；2：收费方产品
            String productType = list.stream().filter(dcPublic -> KiteStringUtils.isEqual(offerId, dcPublic.getCodeb())).findAny().map(DcPublic::getCodec).orElse(null);
            KitePosAttrDTO attr = new KitePosAttrDTO();
            attr.setCode("relationTypeCode");
            attr.setType("STRING");
            attr.setStartDate(createDateStr);
            attr.setEndDate(LocalKeyConsts.ATTR_SEND_DATE);
            attr.setValue("2".equals(productType)?"07":"08");
            attrList.add(attr);

            // 用户角色属性
            List<ProdInstDTO> prodInstLists = querySceneProdInstService.listEffProdInsts(context.getSceneInstId(), context.getCustId()).getResultObject();
            if(KiteListUtils.isNotEmpty(prodInstLists)) {
                List<InstAttrDTO> instAttrDTOS = prodInstLists.get(0).getInstAttrDTOS();
                String role = instAttrDTOS.stream().filter(instAttrDTO -> KiteStringUtils.isEqual("200002061", instAttrDTO.getFieldName()))
                    .findAny().map(InstAttrDTO::getValue).orElse(null);

                attr = new KitePosAttrDTO();
                attr.setCode("role");
                attr.setType("STRING");
                attr.setStartDate(createDateStr);
                attr.setEndDate(LocalKeyConsts.ATTR_SEND_DATE);
                attr.setValue(getRoleByProdAttrValue(role));
                attrList.add(attr);
            }
        }

        if (CuccPosServiceUtils.isRouteUser(context.getSceneInstId(), context.getCustId())) {
            user.setOpenDate(createDateStr);
            String userLocation = querySceneInstService
                .getCommonAttrValue(context.getSceneInstId(), "user_location");
            if (KiteStringUtils.isEmpty(userLocation)) {
                userLocation = querySceneInstService
                    .getCommonAttrValue(context.getSceneInstId(), "contact_info_location");
            }
            user.setProvinceCode(userLocation.split(",")[0]);
            user.setCityCode(userLocation.split(",").length > 1 ? userLocation.split(",")[1] : "");
            user.setDistrictCode(userLocation.split(",").length > 2 ? userLocation.split(",")[2] : "");

            //国际业务特殊处理，针对没有区县的客户，把地市信息作为区县传下去
            UserInfo simpleLoginInfo = ContextUtil.getLoginInfo().getUserInfo();
            if(KiteStringUtils.isEmpty(user.getDistrictCode())&&simpleLoginInfo.getPostProvinceNbr().startsWith("48")||simpleLoginInfo.getPostProvinceNbr().startsWith("49")){
                user.setDistrictCode(user.getCityCode());
            }
            this.packageUserAttrs(attrList, user, context, createDateStr);
        }
        if (KiteStringUtils.isEqual(bizType, LocalServiceOfferConsts.SERVICE_OFFER_ORDER)||KiteStringUtils.isEqual(
            bizType, LocalServiceOfferConsts.SERVICE_OFFER_ORDER_OPPER)) {
            user.setChangeType(ChangeTypeUtils.CHANGE_TYPE_A);
        }
        this.setUserDiffCode(user, kiteSceneInst);
        return user;
    }

    protected void packageUserAttrs(List<KitePosAttrDTO> attrList, KitePosUserDTO user, KitePosHandlerContext context, String createDateStr) {
        List<KiteAttr> busiAttrs = Lists.newArrayList();
        busiAttrs.addAll(querySceneInstService.listCommonAttrsByModuleId(context.getSceneInstId(), LocalKeyConsts.CUSTMANAGERINFO_MODULEID));
        busiAttrs.addAll(querySceneInstService.listCommonAttrsByModuleId(context.getSceneInstId(), LocalKeyConsts.GROUPUSERINFO_MODULEID));
        busiAttrs = busiAttrs.stream().filter(attr -> !KiteStringUtils.equals(attr.getShowType(), LocalKeyConsts.KITE_ATTR_CONFIG_SHOW_TYPE_H) ||
            KiteStringUtils.equalsAny(attr.getFieldName(), LocalKeyConsts.BUSINESS_NEW, LocalKeyConsts.VIK_BUSINESS_CODE,
                LocalKeyConsts.VIK_BUSINESS_CODE_NEW, LocalKeyConsts.IS_LEADER_CHARGE_NEW, LocalKeyConsts.IS_LEADER_SIGN_NEW)).collect(Collectors.toList());
        busiAttrs = busiAttrs.stream().filter(attr -> isFilterField(attr.getFieldName())).collect(Collectors.toList());
        List<KiteAttr> busiAttrsC = busiAttrs;
        for (KiteAttr kiteAttr : busiAttrs) {
            if (!attrList.stream().anyMatch((attr) -> attr.getCode().equals(kiteAttr.getFieldName()))) {
                KitePosAttrDTO attr = new KitePosAttrDTO();
                // 是否总部收费
                if (KiteStringUtils.equalsAny(kiteAttr.getFieldName(), "ORD10125", "CON3014")) {
                    if (attrList.stream().anyMatch(attrr -> KiteStringUtils.equals(attrr.getCode(), "CON3014"))) {
                        attrList.removeIf(attrr -> KiteStringUtils.equals(attrr.getCode(), "CON3014"));
                    }
                    kiteAttr.setFieldName("CON3014");
                    if (KiteStringUtils.equals("1_0000107", kiteAttr.getValue())) {
                        kiteAttr.setValue("0");
                        // 接口提交枚举值与销售配置枚举值不同，转化时，同时转化原始值，否则changeType状态不对
                        if(KiteStringUtils.equals("1_0000107", kiteAttr.getOriginValue())) {
                            kiteAttr.setOriginValue("0");
                        }
                    }
                    else if (KiteStringUtils.equals("1_0000106", kiteAttr.getValue())) {
                        kiteAttr.setValue("1");
                        if(KiteStringUtils.equals("1_0000106", kiteAttr.getOriginValue())) {
                            kiteAttr.setOriginValue("1");
                        }
                    }
                }
                // 是否总部直签客户
                if (KiteStringUtils.equals("ORD10129", kiteAttr.getFieldName())) {
                    if (attrList.stream().anyMatch(attrr -> KiteStringUtils.equals(attrr.getCode(), "CON3015"))) {
                        attrList.removeIf(attrr -> KiteStringUtils.equals(attrr.getCode(), "CON3015"));
                    }
                    kiteAttr.setFieldName("CON3015");
                }
                attr.setCode(kiteAttr.getFieldName());
                attr.setType("STRING");
                attr.setStartDate(createDateStr);
                attr.setEndDate(LocalKeyConsts.ATTR_SEND_DATE);
                attr.setValue(kiteAttr.getValue() == null ? "" : kiteAttr.getValue());
                if (CuccPosServiceUtils.isProdModify(context.getSceneInstId())) {
                    // 属性不存在返回的用户属性中，初始值为空，当前值不为空，则视为新增操作
                    if (KiteStringUtils.isNotEmpty(kiteAttr.getValue()) && KiteStringUtils.isEmpty(kiteAttr.getOriginValue())) {
                        attr.setChangeType(ChangeTypeUtils.CHANGE_TYPE_A);
                    } else {
                        String changeType = KiteStringUtils.equals(kiteAttr.getOriginValue(), kiteAttr.getValue()) ? ChangeTypeUtils.CHANGE_TYPE_K : ChangeTypeUtils.CHANGE_TYPE_M;
                        attr.setChangeType(changeType);
                    }
                }
                attrList.add(attr);
            }
            else {
                //如果有匹配的属性并且值不相等,那么取场景中的数据更新转单
                KitePosAttrDTO posAttr = attrList.stream()
                    .filter(attr -> attr.getCode().equals(kiteAttr.getFieldName()) && !attr.getValue().equals(kiteAttr.getValue()))
                    .findFirst().orElse(null);
                if (Objects.nonNull(posAttr)) {
                    posAttr.setValue(kiteAttr.getValue() == null ? "" : kiteAttr.getValue());
                    if (CuccPosServiceUtils.isProdModify(context.getSceneInstId())) {
                        // 二次业务 如果属性是隐藏的, 并且值不相等，并且当前值为空，旧值不为空，就传删除动作
                        if (KiteStringUtils.equals(kiteAttr.getShowType(), LocalKeyConsts.KITE_ATTR_CONFIG_SHOW_TYPE_H) &&
                            KiteStringUtils.isEmpty(kiteAttr.getValue()) && KiteStringUtils.isNotEmpty(kiteAttr.getOriginValue())) {
                            // 删除动作，值不能为空，结束时间可不传或传竣工时间
                            posAttr.setValue(kiteAttr.getOriginValue());
                            posAttr.setEndDate(createDateStr);
                            posAttr.setChangeType(ChangeTypeUtils.CHANGE_TYPE_D);
                        } else {
                            String changeType = KiteStringUtils.equals(kiteAttr.getOriginValue(), kiteAttr.getValue()) ? ChangeTypeUtils.CHANGE_TYPE_K : ChangeTypeUtils.CHANGE_TYPE_M;
                            posAttr.setChangeType(changeType);
                        }
                    }
                }
            }
        }
        if(!KiteListUtils.isEmpty(attrList)) {
            attrList = attrList.stream().filter(attr -> isFilterField(attr.getCode())).collect(Collectors.toList());
            if (CuccPosServiceUtils.isProdModify(context.getSceneInstId())) {
                for (KitePosAttrDTO posAttr : attrList) {
                    if (KiteStringUtils.isEmpty(posAttr.getChangeType())) {
                        posAttr.setChangeType(ChangeTypeUtils.CHANGE_TYPE_K);
                    }
                }
                List<KitePosAttrDTO> changeAttrList = attrList.stream().filter(attr -> KiteStringUtils.equals(attr.getChangeType(), ChangeTypeUtils.CHANGE_TYPE_M)).collect(Collectors.toList());
                if (KiteListUtils.isEmpty(changeAttrList)) {
                    user.setChangeType(ChangeTypeUtils.CHANGE_TYPE_K);
                } else {
                    user.setChangeType(ChangeTypeUtils.CHANGE_TYPE_M);
                }
            }
            user.setAttrs(attrList);
        }
    }

    /**
     * 归集集团Users节点特殊处理
     *
     * @param user 用户节点
     * @param kiteSceneInst 场景实例对象关系
     *
     */
    protected void setUserDiffCode(KitePosUserDTO user, KiteSceneInst kiteSceneInst) {
        if (!KiteStringUtils.isEmpty(user.getUserDiffCode())) {
            return;
        }
        if (Objects.equals(InstType.GIFT_OFFER_INST, kiteSceneInst.getRootInstType())) {
            user.setUserDiffCode("-1");
            return;
        }
        if (KiteDcPublicUtils.isCollectionGroup(kiteSceneInst.getSceneInstId())) {
            user.setOpenDate(KiteDateUtils.formatDate(kiteSceneInst.getCreateDate(), KiteDateUtils.DATE_TIME_FORMAT_14));
            user.setUserDiffCode("28");
        }
        else {
            user.setUserDiffCode("00");
        }
    }

    private boolean isFilterField(String filedName) {
        boolean result = true;
        DcPublic dp = DcPublicCache.get("20210208001",filedName);
        if(Objects.nonNull(dp)) {
            result = false;
        }
        return result;
    }

    protected String getOfferCatagoryId(String userInstId, List<KitePosGoodsDTO> goodsList) {
        goodsList = goodsList.stream()
            .filter(goods -> (KiteStringUtils.equals(userInstId, goods.getUserInstId())
                && !GoodsInfoTransfer.isAddRoleOffer(goods.getCode(), OfferCache.get(goods.getCode()).getCateId())))
            .collect(Collectors.toList());
        if (!KiteListUtils.isEmpty(goodsList)) {
            String offerId = goodsList.get(0).getCode();
            return OfferCache.get(offerId).getCateId();
        }
        return  "";
    }

    protected void addUserSourceAttr(List<KitePosAttrDTO> attrList, Map<String, Object> groupUserInfo, String createDateStr) {
        KitePosAttrDTO attr = new KitePosAttrDTO();
        attr.setCode("ORD10262");
        attr.setValue(KiteMapUtils.getString(groupUserInfo, "user_source"));
        attr.setType("STRING");
        attr.setStartDate(createDateStr);
        attr.setEndDate(LocalKeyConsts.ATTR_SEND_DATE);
        attr.setChangeType(ChangeTypeUtils.CHANGE_TYPE_K);
        attrList.add(attr);
    }

    /**
     * 根据产品属性-用户角色，获取接口users.attrs下传的role属性值编码
     * @author zhang.song
     * @date 2022-02-15 11:48
     * @param attrValue
     * @return java.lang.String
     */
    private static String getRoleByProdAttrValue(String attrValue) {
        String role;
        switch (attrValue) {
            case "100003207":
                // 落地方产品-A(CE)端落地
                role = "0";
                break;
            case "100003208":
                // 落地方产品-Z(PE)端落地
                role = "1";
                break;
            case "100003209":
                // 落地方产品-第三方收费
                role = "2";
                break;
            case "110009565":
                // 收费方产品-收费方
                role = "2";
                break;
            default:
                role = "0";
                break;
        }
        return role;
    }
}
